﻿#pragma once

/*
    SQL查询生成器，用于生成SQL查询语句：
        除 数据库、表结构 等基本的数据操作外，其它日常的增、删、改、查的SQL语句，
        尽量用这个引擎来生成，利于减少拼写错误，以及将来扩展到其它数据库
*/
namespace sqlengine {
class ExprQuery;
typedef std::shared_ptr<ExprQuery> ExprPtr;

// SQL 表达式
class ExprQuery : public std::enable_shared_from_this<ExprQuery> {
public:
    explicit ExprQuery();
    virtual ~ExprQuery();

    ExprPtr and_(std::string sentence);
    ExprPtr or_(std::string sentence);

    ExprPtr and_begin();
    ExprPtr or_begin();
    ExprPtr end();

    virtual std::string to_string();

private:
    void build_sentence(const char* condition, std::string& sentence);

    ExprPtr build_condition_begin(const char* condition);

private:
    std::string m_result;
    bool        m_being_open;
    std::string m_operation_before;
};

class SelectQuery;
typedef std::shared_ptr<SelectQuery> SelectPtr;

// select 查询
class SelectQuery : public std::enable_shared_from_this<SelectQuery> {
public:
    explicit SelectQuery(std::string field = "");
    virtual ~SelectQuery();

    virtual std::string to_string();

    // SELECT DISTINCT，去除重复数据
    SelectPtr distinct();

    SelectPtr field(std::string field);
    SelectPtr field(std::string field, std::string alias);

    SelectPtr from(std::string from);
    SelectPtr from(std::string from, std::string acronimus);
    SelectPtr from(SelectPtr query, std::string acronimus);

    SelectPtr where(std::string condition);
    SelectPtr where(ExprPtr expr);

    ExprPtr expr();

    SelectPtr limit(int limit);

    SelectPtr offset(int offset);

    SelectPtr order_by(std::string order_by);
    SelectPtr asc();
    SelectPtr desc();

    SelectPtr group_by(std::string group_by);

    SelectPtr join(std::string join);
    SelectPtr join(std::string join, std::string alias);
    SelectPtr join(std::string join, std::string alias, ExprPtr expr);

    SelectPtr outer_join(std::string outer_join);

    SelectPtr left_join(std::string left_join, std::string on_left_join);
    SelectPtr left_join(std::string left_join, std::string alias, std::string on_left_join);

    SelectPtr right_join(std::string right_join, std::string on_right_join);
    SelectPtr right_join(std::string right_join, std::string alias, std::string on_right_join);

private:
    std::string get_string_fields();
    std::string get_string_from();
    std::string get_string_limit();
    std::string get_string_offset();
    std::string get_string_order_by();
    std::string get_string_group_by();
    std::string get_string_where();
    std::string get_string_join();
    std::string get_string_outer_join();
    std::string get_string_left_join();
    std::string get_string_right_join();

private:
    std::string              m_distinct;
    std::vector<std::string> m_fields;
    std::vector<std::string> m_order_by;
    std::vector<std::string> m_from;
    std::vector<std::string> m_where;
    std::vector<std::string> m_group_by;
    int                      m_limit;
    int                      m_offset;
    std::vector<std::string> m_join;
    std::vector<std::string> m_outer_join;
    std::vector<std::string> m_left_join;
    std::vector<std::string> m_right_join;
};

class UpdateQuery;
typedef std::shared_ptr<UpdateQuery> UpdatePtr;

// update 查询
class UpdateQuery : public std::enable_shared_from_this<UpdateQuery> {
public:
    explicit UpdateQuery();
    virtual ~UpdateQuery();

    UpdatePtr table(std::string table);
    UpdatePtr set(std::string field, int value);
    UpdatePtr set(std::string field, double value);
    UpdatePtr set(std::string field, std::string value);
    UpdatePtr where(std::string where);

    virtual std::string to_string();

private:
    std::string get_string_where();
    std::string get_string_set();

private:
    std::string              m_table;
    std::vector<std::string> m_set;
    std::vector<std::string> m_where;
};

class InsertQuery;
typedef std::shared_ptr<InsertQuery> InsertPtr;

// insert 查询
class InsertQuery : public std::enable_shared_from_this<InsertQuery> {
public:
    explicit InsertQuery();
    virtual ~InsertQuery();

    virtual std::string to_string();

    InsertPtr into(std::string into);
    InsertPtr set(std::string field, int value);
    InsertPtr set(std::string field, double value);
    InsertPtr set(std::string field, std::string value);

private:
    std::string get_string_fields();
    std::string get_string_values();

private:
    std::string              m_into;
    std::vector<std::string> m_fields;
    std::vector<std::string> m_values;
};

class DeleteQuery;
typedef std::shared_ptr<DeleteQuery> DeletePtr;

// delete 查询
class DeleteQuery : public std::enable_shared_from_this<DeleteQuery> {
public:
    explicit DeleteQuery();
    virtual ~DeleteQuery();

    virtual std::string to_string();

    DeletePtr from(std::string from);
    DeletePtr where(std::string where);

private:
    std::string get_string_where();

private:
    std::string              m_from;
    std::vector<std::string> m_where;
};

// SQL 引擎，提供方法调用，生成 SQL 语句
class SQL {
public:
    explicit SQL();
    virtual ~SQL();

    // 输出生成的 SQL 语句
    std::string to_string();

    // 提供 SQL select 功能
    std::shared_ptr<SelectQuery> select(std::string field = "");

    // 提供 SQL update 功能
    std::shared_ptr<UpdateQuery> update();

    // 提供 SQL insert 功能
    std::shared_ptr<InsertQuery> insert();

    // 提供 SQL delete 功能，因为与关键字 delete 冲突，所以函数名为 del
    std::shared_ptr<DeleteQuery> del();

    // 提供 SQL 表达式功能
    std::shared_ptr<ExprQuery> expr();

private:
    void clear();

private:
    std::shared_ptr<SelectQuery> m_query_select;
    std::shared_ptr<UpdateQuery> m_query_update;
    std::shared_ptr<InsertQuery> m_query_insert;
    std::shared_ptr<DeleteQuery> m_query_delete;
    std::shared_ptr<ExprQuery>   m_query_expr;
};
};   // namespace sqlengine